using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Net;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.Windows.Forms;
using DirkRettschlag.Utils;

namespace Departure
{
    class BuildDataThread
    {
        ContainerControl sender = null;

        Delegate senderDelegate = null;

        string source = "";

        StationSettings stationSettings;

        public BuildDataThread(ContainerControl sender, Delegate senderDelegate, string Source, StationSettings stationSettings)
        {
            this.sender = sender;
            this.senderDelegate = senderDelegate;
            this.source = Source;
            this.stationSettings = stationSettings;
        }

        /// <summary>
        /// Method for ThreadStart delegate
        /// </summary>
        public void RunProcess()
        {
            Thread.CurrentThread.IsBackground = true; //make them a daemon
            LocalRunProcess();
        }

        /// <summary>
        /// Local Method for the actual work.
        /// </summary>
        private void LocalRunProcess()
        {
            GetTrainsHTML();
        }

        private void GetTrainsHTML()
        {
            try
            {

                string Time;
                string Train;
                string Icon;
                string Direction;
                string Platform;
                string Later;
                string FullDateTime;

                int currentItem = 0;
                int allItems = 0;

                if (this.source.IndexOf("Current departure time in") >= 0)
                {
                    Regex regexCountColumns = new Regex("<th class=\"(time|icon|train|route|platform|ris).*?>.+?</th>", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.CultureInvariant | RegexOptions.Compiled);

                    int countColumns = regexCountColumns.Matches(this.source).Count;

                    // <tr>.*?<td class=\"time\".*?>(?<Time>.*?)</td>.*?<td class=\"train\".*?>.*?<img src=\"(?<Icon>.*?)_24x24.gif.*?<td class=\"train\".*?>.*?<a href.*?>(?<Train>.*?)</a>.*?<td class=\"route\".*?>.*?<a.*?href.*?>(?<Direction>.*?)</a>.*?</td>.*?<td class=\"platform\".*?>(?<Platform>.*?)<br />.*?</td>.*?<td class=\"ris\".*?>(?<Later>.*?)</td>

                    Regex regex;
                    if (countColumns == 4)
                    {
                        regex = new Regex("<tr>.*?<td class=\"time\".*?>(?<Time>.*?)</td>.*?<td class=\"train\".*?>.*?<img src=\"(?<Icon>.*?)_24x24.gif.*?<td class=\"train\".*?>.*?<a href.*?>(?<Train>.*?)</a>.*?<td class=\"route\".*?>.*?<a.*?href.*?>(?<Direction>.*?)</a>.*?</td>", RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
                    }
                    else if (countColumns == 5)
                    {
                        regex = new Regex("<tr>.*?<td class=\"time\".*?>(?<Time>.*?)</td>.*?<td class=\"train\".*?>.*?<img src=\"(?<Icon>.*?)_24x24.gif.*?<td class=\"train\".*?>.*?<a href.*?>(?<Train>.*?)</a>.*?<td class=\"route\".*?>.*?<a.*?href.*?>(?<Direction>.*?)</a>.*?</td>.*?<td class=\"platform\".*?>(?<Platform>.*?)<br />.*?</td>", RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
                    }
                    else if (countColumns == 6)
                    {
                        regex = new Regex("<tr>.*?<td class=\"time\".*?>(?<Time>.*?)</td>.*?<td class=\"train\".*?>.*?<img src=\"(?<Icon>.*?)_24x24.gif.*?<td class=\"train\".*?>.*?<a href.*?>(?<Train>.*?)</a>.*?<td class=\"route\".*?>.*?<a.*?href.*?>(?<Direction>.*?)</a>.*?</td>.*?<td class=\"platform\".*?>(?<Platform>.*?)<br />.*?</td>.*?<td class=\"ris\".*?>(?<Later>.*?)</td>", RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
                    }
                    else
                    {
                        throw new Exception("Source not valid.");
                    }

                    this.source = Regex.Replace(this.source, "^.*?<tr class=\"browse\">", "", RegexOptions.Singleline | RegexOptions.CultureInvariant | RegexOptions.Compiled);
                    this.source = Regex.Replace(this.source, "<tr class=\"browse\">.*", "", RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
#if DEBUG
                    Stopwatch stopWatch = Stopwatch.StartNew();
#endif                    
                    MatchCollection matchcollection = regex.Matches(this.source);
#if DEBUG
                    stopWatch.Stop();
                    Debug.WriteLine("GetTrainsHTML Regex Time:   " + stopWatch.ElapsedMilliseconds.ToString());
#endif
                    //allItems = Regex.Matches(this.source, "<tr.*?>.*?</tr>", RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled).Count;

                    if (matchcollection != null)
                        allItems = matchcollection.Count;

#if DEBUG
                    stopWatch = Stopwatch.StartNew();
#endif
                    if (allItems > 0)
                    {

                        foreach (Match tmpmatch in matchcollection)
                        {
                            currentItem++;

                            this.sender.BeginInvoke(this.senderDelegate, new object[] { "", "", "", "", "", "", "", "", false, false, true, currentItem, allItems });

                            Time = ClearTime(Utilities.ClearText(tmpmatch.Groups["Time"].Value)).Trim();
                            Train = ClearTrain(Utilities.ClearText(tmpmatch.Groups["Train"].Value)).Trim();
                            Icon = ClearIcon(tmpmatch.Groups["Icon"].Value);
                            Direction = Utilities.ClearText(tmpmatch.Groups["Direction"].Value).Trim();

                            if (tmpmatch.Groups.Count >= 4)
                                Platform = ClearPlatform(Utilities.ClearText(tmpmatch.Groups["Platform"].Value)).Trim();
                            else
                                Platform = "";

                            if (tmpmatch.Groups.Count >= 5)
                                Later = ClearLater(Utilities.ClearText(tmpmatch.Groups["Later"].Value)).Trim();
                            else
                                Later = "";

                            if (FilterData(Train, Direction, Platform))
                            {
                                DateTime FullDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, int.Parse(Time.Split(':')[0]), int.Parse(Time.Split(':')[1]), 0);

                                if (FullDate < DateTime.Now.AddMinutes(-2))
                                    FullDate = FullDate.AddDays(1);

                                FullDateTime = FullDate.ToFileTimeUtc().ToString();

                                this.sender.BeginInvoke(this.senderDelegate, new object[] { Time, Train, Icon, Direction, Platform, Later, FullDateTime, "", false, false, false, 0, 0 });
                            }
                        }
                    }
                    else
                    {
                        throw new Exception("No departures found.");
                    }
#if DEBUG
                    stopWatch.Stop();
                    Debug.WriteLine("GetTrainsHTML Parse Departures Time:   " + stopWatch.ElapsedMilliseconds.ToString());
#endif

                }
                else
                {
                    throw new Exception("No departures found.");
                }

                this.sender.BeginInvoke(this.senderDelegate, new object[] { "", "", "", "", "", "", "", "", false, true, false, 0, 0 });
            }
            catch (Exception ex)
            {
                this.sender.BeginInvoke(this.senderDelegate, new object[] { "", "", "", "", "", "", "", ex.Message, true, false, false, 0, 0 });
            }
        }

        private bool FilterData(string Train, string Direction, string Platform)
        {
            Regex regex;

            bool filterhitTrain = false;
            bool filterhitDirection = false;
            bool filterhitPlatform = false;

            //// Bus Filter
            //regex = new Regex("^Bus", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
            //if (this.stationSettings.TransfersSelected[7].ToString() == "0" && regex.Match(Train).Success)
            //    return false;
            //// IRE Filter
            //regex = new Regex("^IRE", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
            //if (this.stationSettings.TransfersSelected[3].ToString() == "0" && regex.Match(Train).Success)
            //    return false;
            //// RE Filter
            //regex = new Regex("^RE", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
            //if (this.stationSettings.TransfersSelected[4].ToString() == "0" && regex.Match(Train).Success)
            //    return false;
            //// RB Filter
            //regex = new Regex("^RB", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
            //if (this.stationSettings.TransfersSelected[5].ToString() == "0" && regex.Match(Train).Success)
            //    return false;

            // Train Filter
            if (this.stationSettings.UseTrainsFilter)
            {
                List<string> filterTrains = new List<string>(this.stationSettings.TrainsFilter.Split(';'));

                foreach (string filterTrain in filterTrains)
                {
                    if (Train.ToLower()== filterTrain.ToLower())
                    {
                        filterhitTrain = true;
                    }
                }

                //regex = new Regex(this.stationSettings.TrainsFilter.Replace(";", "|"), RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
                //if (regex.Match(Train).Success)
                //{
                //    filterhitTrain = true;
                //}
            }

            // Direction Filter
            if (this.stationSettings.UseDirectionsFilter)
            {
                regex = new Regex(this.stationSettings.DirectionsFilter.Replace(";", "|"), RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
                if (regex.Match(Direction).Success)
                {
                    filterhitDirection = true;
                }
            }

            // Platform Filter
            if (this.stationSettings.UsePlatformsFilter)
            {
                List<string> filterPlatforms = new List<string>(this.stationSettings.PlatformsFilter.Split(';'));

                foreach (string filterPlatform in filterPlatforms)
                {
                    if (Platform.ToLower() == filterPlatform.ToLower())
                    {
                        filterhitPlatform = true;
                    }
                }

                //regex = new Regex(this.stationSettings.PlatformsFilter.Replace(";", "|"), RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
                //if (regex.Match(Platform).Success)
                //{
                //    filterhitPlatform = true;
                //}
            }

            if (this.stationSettings.UseAndFilter)
            {
                if (this.stationSettings.UseTrainsFilter == true && this.stationSettings.UseDirectionsFilter == false && this.stationSettings.UsePlatformsFilter == false)
                    return filterhitTrain;
                else if (this.stationSettings.UseTrainsFilter == true && this.stationSettings.UseDirectionsFilter == true && this.stationSettings.UsePlatformsFilter == false)
                    return (filterhitTrain && filterhitDirection);
                else if (this.stationSettings.UseTrainsFilter == true && this.stationSettings.UseDirectionsFilter == true && this.stationSettings.UsePlatformsFilter == true)
                    return (filterhitTrain && filterhitDirection && filterhitPlatform);
                else if (this.stationSettings.UseTrainsFilter == true && this.stationSettings.UseDirectionsFilter == false && this.stationSettings.UsePlatformsFilter == true)
                    return (filterhitTrain && filterhitPlatform);
                else if (this.stationSettings.UseTrainsFilter == false && this.stationSettings.UseDirectionsFilter == false && this.stationSettings.UsePlatformsFilter == true)
                    return (filterhitPlatform);
                else //if (this.stationSettings.useTrainsFilter == false && this.stationSettings.useDirectionsFilter == true && this.stationSettings.usePlatformsFilter == false)
                    return (filterhitDirection);
            }
            else
                if (this.stationSettings.UseTrainsFilter == true || this.stationSettings.UseDirectionsFilter == true || this.stationSettings.UsePlatformsFilter == true)
                    return (filterhitTrain || filterhitDirection || filterhitPlatform);
                else
                    return true;
        }

        private string ClearLater(string input)
        {
            input = Regex.Replace(input, "<.*?>", "", RegexOptions.IgnoreCase | RegexOptions.Singleline);

            input = input.Replace("on time", "");
            input = input.Replace("-", "");
            input = input.Replace("n.a.", "");

            if (input.Length > 1)
            {
                Regex regex = new Regex(".*?(?<Later>approx..*?minute.*?later)", RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
                Match match = regex.Match(input);
                if (match.Groups.Count > 0)
                    input = match.Groups["Later"].Value;
            }

            return input;
        }

        private string ClearPlatform(string input)
        {
            input = Regex.Replace(input, "<.*?>", "", RegexOptions.IgnoreCase | RegexOptions.Singleline);

            input = input.Replace("Platf.", "");

            return input;
        }

        private string ClearTime(string input)
        {
            input = input.Replace(" ", "");

            return input;
        }

        private string ClearDirection(string input)
        {
            input = input.Replace("<", "");
            input = input.Replace(">", "");

            return input;
        }

        private string ClearTrain(string input)
        {
            input = input.Replace("S     ", "");
            input = input.Replace("S    ", "");

            input = input.Replace("U     ", "");
            input = input.Replace("U    ", "");

            input = input.Replace(" ", "");

            return input;
        }

        private string ClearIcon(string input)
        {
            input = input.Remove(0, input.LastIndexOf("/") + 1);

            return input;
        }
    }
}
